package com.duobaoyu.dby.supply.job.task.supply;

import cn.hutool.core.map.MapUtil;
import cn.hutool.script.ScriptUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.stereotype.Component;

import javax.script.SimpleBindings;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chenms
 * @date 2023/12/9 4:39 PM
 */
@Slf4j
@Component
public class SupplyDebugTask {

    @XxlJob("debugJavascript")
    public void debugJavascript() {
        String jobParam = XxlJobHelper.getJobParam();
        log.info("脚本调试参数: {}", jobParam);
        try {
            JavascriptDebugDTO scriptDebugDTO = JSON.parseObject(jobParam, JavascriptDebugDTO.class);
            Object eval = ScriptUtil.eval(scriptDebugDTO.getScript(), new SimpleBindings(Optional.ofNullable(scriptDebugDTO.getParams()).orElse(new HashMap<>())));
            log.info("脚本调试结果: {}", JSON.toJSONString(new DebugResultVO(eval)));
        } catch (Exception e) {
            log.info("脚本解析异常：ex => {}", ExceptionUtils.getStackTrace(e));
        }

    }


    @Data
    public static class DebugResultVO {
        private Object eval;

        private String type;

        private ChannelExceptionScriptResultBO result;

        public DebugResultVO(Object eval) {
            this.eval = eval;
            this.type = Optional.ofNullable(eval).map(item->item.getClass().getName()).orElse(null);
            if(eval instanceof  ScriptObjectMirror) {
                result = new ChannelExceptionScriptResultBO((ScriptObjectMirror) eval);
            }
        }
    }


    @Data
    public static class JavascriptDebugDTO implements Serializable {

        private static final long serialVersionUID = -200214281104838730L;

        /**
         * 脚本
         */
        @NotBlank(message = "脚本不能为空")
        private String script;

        /**
         * 脚本参数
         */
        private Map<String, Object> params;
    }


    @Getter
    @ToString
    @NoArgsConstructor
    @AllArgsConstructor
    public static class ChannelExceptionScriptResultBO implements Serializable {

        /**
         * 异常码
         */
        private String exceptionCode;

        /**
         * 异常信息
         */
        private String exceptionMessage;

        /**
         * 异常数据
         */
        private List<String> exceptionData;


        public ChannelExceptionScriptResultBO(ScriptObjectMirror scriptObjectMirror) {
            exceptionMessage = MapUtil.getQuietly(scriptObjectMirror,"exceptionMessage", String.class, null);
            exceptionCode = MapUtil.getQuietly(scriptObjectMirror,"exceptionCode", String.class, null);
            Object data = MapUtil.getQuietly(scriptObjectMirror,"exceptionData", Object.class, null);
            if (data instanceof String) {
                exceptionData = Lists.newArrayList((String) data);
            } else if (data instanceof ScriptObjectMirror && ((ScriptObjectMirror)data).isArray()) {
                exceptionData = ((ScriptObjectMirror)data).values().stream()
                        .map(item-> Objects.nonNull(item) ? item.toString() : null).collect(Collectors.toList());
            }
        }
    }

}
